package lazy.util;

import java.math.BigDecimal;

class PrimitiveConverter {
	private static BigDecimal convertN(String value) {
		int dotIndex = value.indexOf(".");
		if(dotIndex!=value.lastIndexOf(".")) return new BigDecimal("0");
		StringBuilder s = new StringBuilder();
		for(char c:value.toCharArray()) {
			if(c=='.') {
				s.append(c);
			} else {
				s.append(convertI(c).toString());
			}
		}
		return new BigDecimal(s.toString());
	}
	
	private static Boolean convertBool(Number value) {
		return value.doubleValue()>0;
	}
	private static Boolean convertBool(Character value) {
		return value!='\0';
	}
	private static Boolean convertBool(String value) {
		return "true".equalsIgnoreCase(value);
	}
	private static Boolean convertBool(Object value) {
		if(value==null) return false;
		if(value instanceof Boolean) return (Boolean)value;
		if(value instanceof Number) return convertBool((Number)value);
		if(value instanceof Character) return convertBool((Character)value);
		if(value instanceof String) return convertBool((String)value);
		return true;
	}
	
	private static Integer convertI(Boolean value) {
		return value?1:0;
	}
	private static Integer convertI(Number value) {
		return value.intValue();
	}
	private static Integer convertI(Character value) {
		int c = (int)value.charValue();
		if(48<=c && c<=57) return c-48;
		return 0;
	}
	private static Integer convertI(String value) {
		return convertN(value).intValue();
	}
	private static Integer convertI(Object value) {
		if(value==null) return 0;
		if(value instanceof Integer) return (Integer)value;
		if(value instanceof Boolean) return convertI((Boolean)value);
		if(value instanceof Number) return convertI((Number)value);
		if(value instanceof Character) return convertI((Character)value);
		if(value instanceof String) return convertI((String)value);
		return 0;
	}
	
	private static Float convertF(Boolean value) {
		return convertI(value).floatValue();
	}
	private static Float convertF(Number value) {
		return value.floatValue();
	}
	private static Float convertF(Character value) {
		return convertI(value).floatValue();
	}
	private static Float convertF(String value) {
		return convertN(value).floatValue();
	}
	private static Float convertF(Object value) {
		if(value==null) return 0F;
		if(value instanceof Float) return (Float)value;
		if(value instanceof Boolean) return convertF((Boolean)value);
		if(value instanceof Number) return convertF((Number)value);
		if(value instanceof Character) return convertF((Character)value);
		if(value instanceof String) return convertF((String)value);
		return 0F;
	}
	
	private static Double convertD(Boolean value) {
		return convertI(value).doubleValue();
	}
	private static Double convertD(Number value) {
		return value.doubleValue();
	}
	private static Double convertD(Character value) {
		return convertI(value).doubleValue();
	}
	private static Double convertD(String value) {
		return convertN(value).doubleValue();
	}	
	private static Double convertD(Object value) {
		if(value==null) return 0D;
		if(value instanceof Double) return (Double)value;
		if(value instanceof Boolean) return convertD((Boolean)value);
		if(value instanceof Number) return convertD((Number)value);
		if(value instanceof Character) return convertD((Character)value);
		if(value instanceof String) return convertD((String)value);
		return 0D;
	}

	private static Byte convertB(Boolean value) {
		return convertI(value).byteValue();
	}
	private static Byte convertB(Number value) {
		return value.byteValue();
	}
	private static Byte convertB(Character value) {
		return convertI(value).byteValue();
	}
	private static Byte convertB(String value) {
		return convertN(value).byteValue();
	}
	private static Byte convertB(Object value) {
		if(value==null) return 0;
		if(value instanceof Byte) return (Byte)value;
		if(value instanceof Boolean) return convertB((Boolean)value);
		if(value instanceof Number) return convertB((Number)value);
		if(value instanceof Character) return convertB((Character)value);
		if(value instanceof String) return convertB((String)value);
		return 0;
	}
	
	private static Short convertShort(Boolean value) {
		return convertI(value).shortValue();
	}
	private static Short convertShort(Number value) {
		return value.shortValue();
	}
	private static Short convertShort(Character value) {
		return convertI(value).shortValue();
	}
	private static Short convertShort(String value) {
		return convertN(value).shortValue();
	}
	private static Short convertShort(Object value) {
		if(value==null) return 0;
		if(value instanceof Short) return (Short)value;
		if(value instanceof Boolean) return convertShort((Boolean)value);
		if(value instanceof Number) return convertShort((Number)value);
		if(value instanceof Character) return convertShort((Character)value);
		if(value instanceof String) return convertShort((String)value);
		return 0;
	}
	
	private static Long convertL(Boolean value) {
		return convertL(value).longValue();
	}
	private static Long convertL(Number value) {
		return value.longValue();
	}
	private static Long convertL(Character value) {
		return convertI(value).longValue();
	}
	private static Long convertL(String value) {
		return convertN(value).longValue();
	}
	private static Long convertL(Object value) {
		if(value==null) return 0L;
		if(value instanceof Long) return (Long)value;
		if(value instanceof Boolean) return convertL((Boolean)value);
		if(value instanceof Number) return convertL((Number)value);
		if(value instanceof Character) return convertL((Character)value);
		if(value instanceof String) return convertL((String)value);
		return 0L;
	}
	
	private static Character convertC(Boolean value) {
		return value?'T':'F';
	}
	private static Character convertC(Number value) {
		int codePoint = value.intValue();
		return Character.isValidCodePoint(codePoint)?(char)codePoint:'\n';
	}
	private static Character convertC(String value) {
		return value.toCharArray()[0];
	}
	private static Character convertC(Object value) {
		if(value==null) return '\0';
		if(value instanceof Character) return (Character)value;
		if(value instanceof Boolean) return convertC((Boolean)value);
		if(value instanceof Number) return convertC((Number)value);
		if(value instanceof String) return convertC((String)value);
		return '\0';
	}
	
	/**
	 * @param cls
	 * 可轉換的型態：Number、Character、Boolean。
	 * @param value
	 * 可轉換的值：Number、Character、Boolean、String。
	 * @return
	 */
	static Object convert(Class<?> cls, Object value) {
		if(Boolean.class.equals(cls)	|| Boolean.TYPE.equals(cls)  ) return convertBool(value);
		if(Integer.class.equals(cls)	|| Integer.TYPE.equals(cls)  ) return convertI(value);
		if(Float.class.equals(cls)		|| Float.TYPE.equals(cls)    ) return convertF(value);
		if(Double.class.equals(cls)		|| Double.TYPE.equals(cls)   ) return convertD(value);
		if(Byte.class.equals(cls)		|| Byte.TYPE.equals(cls)     ) return convertB(value);
		if(Short.class.equals(cls)		|| Short.TYPE.equals(cls)    ) return convertShort(value);
		if(Long.class.equals(cls)		|| Long.TYPE.equals(cls)     ) return convertL(value);
		if(Character.class.equals(cls)	|| Character.TYPE.equals(cls)) return convertC(value);
		return null;
	}
}
